#ifndef __UDSF_UART_C_
#define __UDSF_UART_C_

#include "udf_global.h"
/*
*   notice:
*   UDSF 同UDF编程：不可调用cstd-lib,只可调用"sdk_ifs_udk_cfg.h"、"sys_api.h"中列出的API函数。
*   UDSF文件内函数均需使用static修饰符，且UDF中以#include "UDSF.c"形式引用
*/

static void udsf_uart_send_byte(uint8_t data) __attribute__((unused));
static void udsf_uart_send_string(char* pStr) __attribute__((unused));
static void udsf_uart_init(uint32_t baudrate,uint8_t boot_flag) __attribute__((unused));
static void udsf_uart_send_data(uint8_t* pData,int data_len) __attribute__((unused));
static void udsf_uart_send_data_base16(uint8_t* pData,int data_len) __attribute__((unused));
static void udsf_uart_send_data_trans(uint8_t*pData,int data_len) __attribute__ ((unused));
static int  udsf_uart_recv_frame_data(uint8_t* pData,int max_len) __attribute__ ((unused));
static void udsf_uart_send_u32_base16(int endian,uint32_t* Data,int data_len,char* start,char*end) __attribute__ ((unused));
static void udsf_uart_send_u16_base16(int endian,uint16_t* Data,int data_len,char* start,char*end) __attribute__ ((unused));
static void udsf_uart_send_u8_base16(uint8_t* Data,int data_len,char* start,char*end) __attribute__ ((unused));
static void udsf_uart_recv_init(void) __attribute__ ((unused));
static void udsf_uart_recv_enable(void)  __attribute__((unused));
static void udsf_uart_recv_disable(void) __attribute__((unused));

static void udsf_uart_init(uint32_t baudrate,uint8_t boot_flag){
	
	uint32_t raw_baud;
	
	if( boot_flag == 0 ){
		 raw_baud = 640000000/baudrate;
	}else{
		raw_baud = 320000000/baudrate;
	}

	uint32_t baud_div = raw_baud>>4;
	uint32_t baud_mod = ((raw_baud>>1)&0x7) + (raw_baud&0x1);
	USCI1->MOD = (USCI_BAUD_SDIV_Msk & (baud_mod << USCI_BAUD_SDIV_Pos));
	USCI1->MOD &= ~USCI_BAUD_S16_Msk;
	USCI1->BAUD = USCI_BAUD_DIV_Msk &((baud_div>0)?(baud_div-1):(baud_div));
	;// code@rom init uart already,just change baudrate
}

static void udsf_uart_send_byte(uint8_t data){
	USCI1->TRX = data;
	while((Read_M32(0x40004014)&USCI_ISR_TXE_Msk)==0); //USCI1 ISR		
}

static void udsf_uart_send_string(char* pStr){
	
		
	USCI1->ISR = USCI_ISR_TXE_Msk | USCI_ISR_TE_Msk;
	int i;
	for( i=0;;i++ ){
		if( pStr[i] == '\0' ){
			break;
		}
		USCI1->TRX = pStr[i];
		while((Read_M32(0x40004014)&USCI_ISR_TXE_Msk)==0);
	}
	if( i>0){
		while((USCI1->ISR&USCI_ISR_TE_Msk)==0);
		USCI1->ISR = USCI_ISR_TXE_Msk | USCI_ISR_TE_Msk;
	}
}

static void udsf_uart_send_data(uint8_t* pData,int data_len){
	
	if( data_len < 1 ){
		return;
	}
	USCI1->ISR = USCI_ISR_TXE_Msk | USCI_ISR_TE_Msk;
	for( int i=0;i<data_len;i++ ){
		USCI1->TRX = pData[i];
		while((Read_M32(0x40004014)&USCI_ISR_TXE_Msk)==0);
	}
	while((USCI1->ISR&USCI_ISR_TE_Msk)==0);
	USCI1->ISR = USCI_ISR_TXE_Msk | USCI_ISR_TE_Msk;
}

/*send data and 0xff->0xfd 0x02 0xfe->0xfd 0x01 0xfd->0xfd 0x00 */
static void udsf_uart_send_data_trans(uint8_t*pData,int data_len){
	uint8_t data;

	if( data_len < 1 ){
		return;
	}
	USCI1->ISR = USCI_ISR_TXE_Msk | USCI_ISR_TE_Msk;
	
	for( int i=0;i<data_len;i++ ){
		if( pData[i] > 0xfc ){
			USCI1->TRX = 0xfd;
			data = pData[i] - 0xfd;
			while((Read_M32(0x40004014)&USCI_ISR_TXE_Msk)==0);
			USCI1->TRX = data;
		}
		else{
			USCI1->TRX = pData[i];
		}
		while((Read_M32(0x40004014)&USCI_ISR_TXE_Msk)==0);
	}
	
	while((USCI1->ISR&USCI_ISR_TE_Msk)==0);
	USCI1->ISR = USCI_ISR_TXE_Msk | USCI_ISR_TE_Msk;
}

/*endian: 0 -> little-endian 1-> big-enndian*/
static void udsf_uart_send_u32_base16(int endian,uint32_t* Data,int data_len,char* start,char*end){

	uint8_t data[4];
	if( start ){
		udsf_uart_send_string(start);
	}
	for ( int i = 0;i<data_len;i++){
		if( endian == 0 ){
			*((uint32_t*)(&data)) = Data[i];
		}else{
			data[0] = Data[i]>>24;
			data[1] = Data[i]>>16;
			data[2] = Data[i]>>8;
			data[3] = Data[i];
		}
		udsf_uart_send_data_base16(data,sizeof(data));
	}
	if( end ){
		udsf_uart_send_string(end);
	}
}

/*endian: 0 -> little-endian 1-> big-enndian*/
static void udsf_uart_send_u16_base16(int endian,uint16_t* Data,int data_len,char* start,char*end){

	uint8_t data[2];
	if( start ){
		udsf_uart_send_string(start);
	}
	for ( int i = 0;i<data_len;i++){
		if( endian == 0 ){
			*((uint16_t*)(&data)) = Data[i];
		}else{
			data[0] = Data[i]>>8;
			data[1] = Data[i];
		}
		udsf_uart_send_data_base16(data,sizeof(data));
	}
	if( end ){
		udsf_uart_send_string(end);
	}
}


/*endian: 0 -> little-endian 1-> big-enndian*/
static void udsf_uart_send_u8_base16(uint8_t* Data,int data_len,char* start,char*end){

	if( start ){
		udsf_uart_send_string(start);
	}
	
	udsf_uart_send_data_base16(Data,data_len);
	
	if( end ){
		udsf_uart_send_string(end);
	}
}


static void udsf_uart_send_data_base16(uint8_t* pData,int data_len){

	uint8_t tmp_dataA,tmp_dataB,tmp_out;

	if( data_len < 1 ){
		return;
	}
	USCI1->ISR = USCI_ISR_TXE_Msk | USCI_ISR_TE_Msk;
	
	for( int i=0;i<data_len;i++ ){
		tmp_dataA = (pData[i]&0xf0)>>4;
		if( tmp_dataA > 9 ){
			tmp_out = 'A'+(tmp_dataA-10);
		}else{
			tmp_out = '0'+tmp_dataA;
		}
		USCI1->TRX = tmp_out;  // send high-4-bit
		
		tmp_dataB = (pData[i]&0x0f);
		if( tmp_dataB > 9 ){
			tmp_out = 'A'+(tmp_dataB-10);
		}else{
			tmp_out = '0'+tmp_dataB;
		}
		while((Read_M32(0x40004014)&USCI_ISR_TXE_Msk)==0);
		USCI1->TRX = tmp_out;  // send low-4-bit
		while((Read_M32(0x40004014)&USCI_ISR_TXE_Msk)==0);
		USCI1->TRX = ' ';      // send space
		while((Read_M32(0x40004014)&USCI_ISR_TXE_Msk)==0);
	}
	
	while((USCI1->ISR&USCI_ISR_TE_Msk)==0);
	USCI1->ISR = USCI_ISR_TXE_Msk | USCI_ISR_TE_Msk;
}

struct uart_rom_def
{
	uint8_t rsv1;  
	uint32_t len;     // 帧长度
	uint8_t flag;     // 接收有效帧标识
	uint8_t rsv2;
	uint8_t data[50]; // 缓存区
	uint8_t rsv3;
	uint32_t rsv4;
	uint32_t rsv5;
};


static void udsf_uart_recv_init(void){
	/* disable uart irq */
	NVIC->ICER[0] = (1 << ((uint32_t)(USCI1_IRQn) & 0x1F));
	USCI1->IMR=0xFFFFFFFF;	

	uint8_t * p_rom_global_workmode = p_work_mode;	
	/* set workmode->fake config mode */
	*p_rom_global_workmode = 0;

	/* enable uart irq */
	USCI1->ISR = 0x1F;
	USCI1->IMR &= ~USCI_IMR_RXNE_Msk;
	NVIC->ISER[0] = (1 << ((uint32_t)(USCI1_IRQn) & 0x1F));
}

static int udsf_uart_recv_frame_data(uint8_t* pData,int max_len){
	
	int len=-1;
	
	#define p_rom_global_uart_struct ((struct uart_rom_def*)UART_RECV_STRUCT_BASE)
		
	if( p_rom_global_uart_struct->flag ){
	
		len = p_rom_global_uart_struct->len;
		len = len>max_len?max_len:len;
		for( int i=0;i<len;i++){
			pData[i] = p_rom_global_uart_struct->data[i];
		}
		p_rom_global_uart_struct->len = 0;
		p_rom_global_uart_struct->flag = 0;
	}
	#undef p_rom_global_uart_struct
	return len;
}

static void udsf_uart_recv_disable(void){
	NVIC->ICER[0] = (1 << ((uint32_t)(USCI1_IRQn) & 0x1F));
	USCI1->IMR=0xFFFFFFFF;	
}

static void udsf_uart_recv_enable(void){
	USCI1->ISR = 0x1F;
	USCI1->IMR &= ~USCI_IMR_RXNE_Msk;
	NVIC->ISER[0] = (1 << ((uint32_t)(USCI1_IRQn) & 0x1F));
}

#endif

